home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / GNU_C++ / LIB / CFLIB-11.LZH / src / popup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-04  |  10.9 KB  |  489 lines

  1.  
  2. #include "intern.h"
  3.  
  4. static int valid_item(OBJECT *tree, int obj)
  5. {
  6.     int    type;
  7.     int    ret = 0;
  8.     
  9.     type = get_obtype(tree, obj, NULL);
  10.     if (type == G_STRING || type == G_SHORTCUT)
  11.     {
  12.         if (!get_state(tree, obj, DISABLED) && get_flag(tree, obj, SELECTABLE))
  13.             ret = 1;
  14.     }
  15.     return ret;
  16. }
  17.  
  18. /*
  19.  * Emulation/Erweiterung von menu_popup().
  20.  * Falls Button = 0 und das System menu_popup() hat, wird dieses aufgerufen.
  21.  * Ist Button = 1/2 (linke/rechte Maustaste), wird das Popup selbst verwaltet.
  22.  * Es geht dann z.B. sofort auf (nicht wie bei menu_popup() erst beim Loslassen
  23.  * der Taste).
  24.  * offset gibt den Offset zwischen Root und dem ersten Popup-String an (i.d.R.
  25.  * ist offset 0, bei einem Farb-Popup aber z.B. nicht).
  26. */
  27. int cf_menu_popup(MENU *m1, int x, int y, MENU *m2, int button, int offset)
  28. {
  29.     int    i, d;
  30.     
  31.     if ((button == 0) && appl_xgetinfo(9, &d, &i, &d, &d) && (i == 1))    /* gibts menu_popup? */
  32.         return menu_popup(m1, x, y, m2);
  33.     else
  34.     {
  35.         OBJECT    *tree;
  36.         int        root, m_x, m_y, event, item, but,
  37.                     msg[8], olditem, kstate;
  38.         GRECT        box, r;
  39.         MFDB        save;
  40. #ifdef __MTAES__
  41.         EVNTDATA    ev;
  42.         GRECT        n = {0,0,0,0};
  43. #endif
  44.  
  45.         tree = m1->mn_tree;
  46.         root = m1->mn_menu;
  47.         item = m1->mn_item;
  48.         
  49.         tree[root].ob_x = x;
  50.         tree[root].ob_y = y - ((item - offset - root - 1) * tree[item].ob_height);
  51.  
  52.         /* bei RSM liegt der das Popup enthaltende Dialog nicht unbedingt bei (0,0)!! */
  53.         if (root != 0 && tree[0].ob_x > 0)
  54.             tree[0].ob_x = 0;
  55.         if (root != 0 && tree[0].ob_y > 0)
  56.             tree[0].ob_y = 0;
  57.         
  58.         box.g_x = tree[root].ob_x - 1;
  59.         box.g_y = tree[root].ob_y - 1;
  60.         box.g_w = tree[root].ob_width + 4;
  61.         box.g_h = tree[root].ob_height + 4;
  62.  
  63.         wind_update(BEG_MCTRL);
  64.         save_background(&box, &save);
  65.         graf_mouse(ARROW, NULL);
  66.  
  67.         if (button == 0)
  68.             button = 1;
  69. #ifdef __MTAES__
  70.         graf_mkstate(&ev);
  71.         m_x = ev.x;
  72.         m_y = ev.y;
  73.         but = ev.bstate;
  74. #else
  75.         graf_mkstate(&m_x, &m_y, &but, &d);
  76. #endif
  77.  
  78.         if (but & button)        /* Taste noch gedrückt? */
  79.             but = 0;                /* -> evnt_multi wartet auf Loslassen */
  80.         else
  81.             but = 1;                /*    ->                               Drücken */
  82.  
  83. #ifdef __MTAES__
  84.         objc_draw(tree, root, MAX_DEPTH, &box);
  85. #else
  86.         objc_draw(tree, root, MAX_DEPTH, box.g_x, box.g_y, box.g_w, box.g_h);
  87. #endif
  88.         olditem = -1;
  89.         do
  90.         {
  91.             item = objc_find(tree, root, MAX_DEPTH, m_x, m_y);
  92.             if ((item == root) || !valid_item(tree, item))
  93.                 item = -1;
  94.  
  95.             if (item != olditem)
  96.             {
  97.                 if (olditem != -1)
  98. #ifdef __MTAES__
  99.                     objc_change(tree, olditem, 0, &box, tree[olditem].ob_state & (~SELECTED), TRUE);
  100. #else
  101.                     objc_change(tree, olditem, 0, box.g_x, box.g_y, box.g_w, box.g_h, tree[olditem].ob_state & (~SELECTED), TRUE);
  102. #endif
  103.                 if (item != -1)
  104. #ifdef __MTAES__
  105.                     objc_change(tree, item, 0, &box, tree[item].ob_state|SELECTED, TRUE);
  106. #else
  107.                     objc_change(tree, item, 0, box.g_x, box.g_y, box.g_w, box.g_h, tree[item].ob_state|SELECTED, TRUE);
  108. #endif
  109.             }
  110.             if (item != -1)
  111.             {
  112.                 objc_offset(tree, item, &r.g_x, &r.g_y);
  113.                 r.g_w = tree[item].ob_width;
  114.                 r.g_h = tree[item].ob_height;
  115.             }
  116.             else
  117.             {
  118.                 r.g_x = m_x;    
  119.                 r.g_y = m_y;
  120.                 r.g_w = 1;     
  121.                 r.g_h = 1;
  122.             }
  123.             
  124. #ifdef __MTAES__
  125.             event = evnt_multi((MU_BUTTON | MU_M1),
  126.                                       1, button, but,        /* ein Klick, links, s.o. */
  127.                                       1, &r, 0, &n,
  128.                                       msg, 
  129.                                       0L,
  130.                                       &ev,
  131.                                       &d, &d);
  132.             m_x = ev.x;
  133.             m_y = ev.y;
  134.             kstate = ev.kstate;
  135.  
  136.             /* warten, bis die Taste wieder losgelassen wird */
  137.             if (but == 1)
  138.                 evnt_button(1, button, 0, &ev);
  139. #else
  140.             event = evnt_multi((MU_BUTTON | MU_M1),
  141.                                       1, button, but,        /* ein Klick, links, s.o. */
  142.                                       1, r.g_x, r.g_y, r.g_w, r.g_h,
  143.                                       0, 0, 0, 0, 0,
  144.                                       msg, 
  145.                                       0L,
  146.                                       &m_x, &m_y,
  147.                                       &d, &kstate,
  148.                                       &d, &d);
  149.  
  150.             /* warten, bis die Taste wieder losgelassen wird */
  151.             if (but == 1)
  152.                 evnt_button(1, button, 0, &d, &d, &d, &d);
  153. #endif
  154.  
  155.             olditem = item;
  156.         }
  157.         while (!(event&MU_BUTTON));
  158.     
  159.         restore_background(&box, &save);
  160.         wind_update(END_MCTRL);
  161.     
  162.         if (item == -1)
  163.             item = 0;
  164.         else
  165.             tree[item].ob_state &= ~SELECTED;
  166.     
  167.         if (m2 != NULL)
  168.         {
  169.             if (m1 != m2)
  170.                 memcpy(m2, m1, sizeof(MENU));
  171.             m2->mn_item = item;
  172.             m2->mn_keystate = kstate;
  173.         }
  174.         return (item != 0);
  175.     }
  176. }
  177.  
  178.  
  179. /*
  180.  * Popup zur Laufzeit erzeugen.
  181. */
  182. int create_popup(POPUP *p, int anz, int maxlen, char *item)
  183. {
  184.     char    *text;
  185.     int    i;
  186.                     
  187.     p->tree = (OBJECT *) cf_malloc((anz + 1) * sizeof(OBJECT), "create_popup", FALSE);
  188.     if (p->tree == NULL)
  189.         return FALSE;
  190.  
  191.     p->max_item = anz;
  192.     if (maxlen == -1)
  193.         p->item_len = (int)strlen(item);
  194.     else
  195.         p->item_len = maxlen;
  196.     
  197.     /* Box */
  198.     p->tree[0].ob_next   = -1;
  199.     p->tree[0].ob_head   = 1;
  200.     p->tree[0].ob_tail   = 1;
  201.     p->tree[0].ob_type   = G_BOX;
  202.     p->tree[0].ob_flags  = FL3DBAK;
  203.     p->tree[0].ob_state  = SHADOWED;
  204.     p->tree[0].ob_spec.index  = 0x00ff1100L;    /* Rahmen, Farbe ... */
  205.     p->tree[0].ob_x       = 0;
  206.     p->tree[0].ob_y       = 0;
  207.     p->tree[0].ob_width  = p->item_len;
  208.     p->tree[0].ob_height = 1;
  209.     
  210.     /* Speicher für String holen */
  211.     text = strdup(item);
  212.     if (text == NULL)
  213.         return FALSE;
  214.  
  215.     /* 1. Eintrag */
  216.     p->tree[1].ob_next   = 0;
  217.     p->tree[1].ob_head   = -1;
  218.     p->tree[1].ob_tail   = -1;
  219.     p->tree[1].ob_type   = G_STRING;
  220.     p->tree[1].ob_flags  = (SELECTABLE|LASTOB);
  221.     p->tree[1].ob_state  = 0;
  222.     p->tree[1].ob_spec.free_string = text;
  223.     p->tree[1].ob_x       = 0;
  224.     p->tree[1].ob_y       = 0;
  225.     p->tree[1].ob_width  = p->item_len;
  226.     p->tree[1].ob_height = 1;
  227.     
  228.     p->akt_item = 1;
  229.  
  230.     for(i = 0; i <= p->akt_item; i++)
  231.         rsrc_obfix(p->tree, i);
  232.     
  233.     return TRUE;
  234. }
  235.  
  236.  
  237. int free_popup(POPUP *p)
  238. {
  239.     int    i;
  240.     
  241.     if (p->tree == NULL)
  242.         return FALSE;
  243.     else
  244.     {
  245.         i = -1;
  246.         do
  247.         {
  248.             i++;
  249.             if (get_obtype(p->tree, i, NULL) == G_STRING)
  250.                 Mfree((char *)get_obspec(p->tree, i));    /* free_string freigeben */
  251.         }
  252.         while (!(p->tree[i].ob_flags & LASTOB));
  253.         Mfree(p->tree);
  254.         return TRUE;
  255.     }
  256. }
  257.  
  258.  
  259. int append_popup(POPUP *p, char *item)
  260. {
  261.     char    *text;
  262.     int    i, state;
  263.  
  264.     if (p->tree == NULL)
  265.         return FALSE;
  266.  
  267.     if (p->akt_item >= p->max_item)
  268.         return FALSE;
  269.     
  270.     /* letztes wird vorletztes */
  271.     p->tree[p->akt_item].ob_next  = p->akt_item + 1;
  272.     p->tree[p->akt_item].ob_flags = SELECTABLE;
  273.  
  274.     p->akt_item++;
  275.  
  276.     if (item[0] == '-')
  277.         state = 0x0008;
  278.     else
  279.         state = 0x0000;
  280.         
  281.     /* Speicher für String holen */
  282.     text = strdup(item);
  283.     if (text == NULL)
  284.         return FALSE;
  285.  
  286.     /* neues */
  287.     p->tree[p->akt_item].ob_next    = 0;
  288.     p->tree[p->akt_item].ob_head    = -1;
  289.     p->tree[p->akt_item].ob_tail    = -1;
  290.     p->tree[p->akt_item].ob_type    = G_STRING;
  291.     p->tree[p->akt_item].ob_flags    = (SELECTABLE|LASTOB);
  292.     p->tree[p->akt_item].ob_state    = state;
  293.     p->tree[p->akt_item].ob_spec.free_string = text;
  294.     p->tree[p->akt_item].ob_x    = 0;
  295.     p->tree[p->akt_item].ob_y    = (p->akt_item - 1) * gl_hchar;
  296.     p->tree[p->akt_item].ob_width    = (p->item_len) * gl_wchar;
  297.     p->tree[p->akt_item].ob_height    = 1 * gl_hchar;
  298.  
  299.     /* Box */
  300.     p->tree[0].ob_tail    = p->akt_item;
  301.     p->tree[0].ob_height    = (p->akt_item) * gl_hchar;
  302.  
  303.     for(i = 0; i <= p->akt_item; i++)
  304.     {
  305.         /* zurück auf Zeichenkoor., damit der obfix klappt! */
  306.         p->tree[i].ob_y      /= gl_hchar;
  307.         p->tree[i].ob_width  /= gl_wchar;
  308.         p->tree[i].ob_height /= gl_hchar;
  309.         rsrc_obfix(p->tree, i);
  310.     }
  311.     return TRUE;
  312. }
  313.  
  314.  
  315. int do_popup(POPUP *p, int button)
  316. {
  317.     int    flag, p_x, p_y, d;
  318.     MENU    Menu,
  319.             MData;
  320.  
  321.     Menu.mn_tree   = p->tree;
  322.     Menu.mn_menu   = ROOT;        
  323.     Menu.mn_item   = 0;            
  324.     Menu.mn_scroll = FALSE;        
  325.  
  326. #ifdef __MTAES__
  327. {
  328.     EVNTDATA    ev;
  329.     graf_mkstate(&ev);
  330.     p_x = ev.x;
  331.     p_y = ev.y;
  332. }
  333. #else
  334.     graf_mkstate(&p_x, &p_y, &d, &d);
  335. #endif
  336.  
  337.     flag = cf_menu_popup( &Menu, p_x, p_y, &MData, button, 0);
  338.     return (flag ? MData.mn_item : 0);
  339. }
  340.  
  341.  
  342. int handle_popup(OBJECT *dial, int dial_obj, OBJECT *pop, int pop_obj, int mode)
  343. {
  344.     char    active_str[50] = "", s[50];
  345.     int    first, last, item, i, first_offset;
  346.     int    x, y;
  347.     MENU    m1, m2;
  348.     GRECT    r;
  349.     int    down_pop;
  350.     
  351.     if (pop == NULL)    
  352.         return -1;
  353.  
  354.     first = pop[pop_obj].ob_head;
  355.     while (!valid_item(pop, first))
  356.         first++;
  357.  
  358.     last = pop[pop_obj].ob_tail;
  359.     while (!valid_item(pop, last))
  360.         last--;
  361.  
  362.     /* falls erste Spalte z.B. Farbmarke */
  363.     first_offset = first - pop[pop_obj].ob_head;
  364.  
  365.     item = first;
  366.     down_pop = FALSE;
  367.  
  368.     if (dial != NULL)
  369.     {
  370.         /* Popup-Typ ermitteln */
  371.         down_pop = (get_obtype(dial, dial_obj, NULL) == G_BOXCHAR);
  372.  
  373.         if (!down_pop)
  374.         {
  375.             /* Zunächst das aktuelle, im Dialog eingetragene Popup-Item suchen */
  376.             get_string(dial, dial_obj, active_str);
  377.             item = first;
  378.             while (item <= last)
  379.             {
  380.                 get_string(pop, item, s);
  381.                 if (strcmp(active_str, s) == 0)
  382.                     break;
  383.                 item++;
  384.             }
  385.             if (item > last)        /* nicht gefunden */
  386.                 item = first;
  387.         }
  388.     }
  389.     
  390.     switch (mode)
  391.     {
  392.         case POP_OPEN:
  393.             /* Position des Popups ermitteln */
  394.             if (dial != NULL)
  395.             {
  396.                 objc_offset(dial, dial_obj, &x, &y);
  397.                 if (down_pop)
  398.                     x -= (pop[1].ob_width - dial[dial_obj].ob_width);
  399.                 else
  400.                 {
  401.                     /* mehrspaltiges Popups? */
  402.                     if (pop[pop_obj].ob_height <= ((item - first) * gl_hchar))
  403.                     {
  404.                         get_objframe(pop, item, &r);
  405.                         x -= r.g_w;
  406.                         item -= (pop[pop_obj].ob_height / gl_hchar);
  407.                     }
  408.                 }
  409.  
  410.                 /* außerhalb des Bildschirms? */
  411.                 get_objframe(pop, pop_obj, &r);
  412.  
  413.                 if (x < gl_desk.g_x)
  414.                     x = gl_desk.g_x;
  415.                 if ((x + r.g_w) > (gl_desk.g_x + gl_desk.g_w))
  416.                     x = (gl_desk.g_x + gl_desk.g_w) - r.g_w;
  417.  
  418.                 i = (last - item + 1) * gl_hchar;
  419.                 if ((y + i) > (gl_desk.g_y + gl_desk.g_h))
  420.                     y = (gl_desk.g_y + gl_desk.g_h) - i;
  421.  
  422.                 i = (item - first) * gl_hchar;
  423.                 if (y - i < gl_desk.g_y)
  424.                     y = gl_desk.g_y + i;
  425.  
  426.             }
  427.             else
  428.             {
  429. #ifdef __MTAES__
  430.                 EVNTDATA    ev;
  431.                 graf_mkstate(&ev);
  432.                 x = ev.x;
  433.                 y = ev.y;
  434. #else
  435.                 graf_mkstate(&x, &y, &i, &i);
  436. #endif
  437.                 get_objframe(pop, item, &r);
  438.                 x -= r.g_w / 2;
  439.                 y -= r.g_h / 2;
  440.                 if (first_offset > 0)
  441.                     y -= (first_offset * gl_hchar);
  442.             }
  443.             m1.mn_tree = pop;
  444.             m1.mn_menu = pop_obj;
  445.             m1.mn_item = item;
  446.             i = cf_menu_popup(&m1, x, y, &m2, 1, first_offset);
  447.             if (i != 0)
  448.                 item = m2.mn_item;
  449.             else
  450.                 item = 0;
  451.             break;
  452.             
  453.         case POP_CYCLE:
  454.             i = 0;
  455.             do
  456.             {
  457.                 item++;
  458.                 i++;
  459.                 if (item > last)
  460.                     item = first;
  461.             }
  462.             while(((pop[item].ob_state & DISABLED) || 
  463.                     !(pop[item].ob_flags & SELECTABLE)) && 
  464.                     i <= last - first);
  465.         
  466.             if (i > last - first) 
  467.                 item = 0;
  468.             break;
  469.         
  470.         default:
  471.             debug("\ahandle_popup: unbekannter Modus %d.\n", mode);
  472.     }
  473.     
  474.     /* Text des neuen Popup-Items in den Dialog eintragen und neu zeichnen */
  475.     if ((!down_pop) && (item > 0) && (dial != NULL))
  476.     {
  477.         get_string(pop, item, s);
  478.         set_string(dial, dial_obj, s);
  479.         get_objframe(dial, dial_obj, &r);
  480. #ifdef __MTAES__
  481.         objc_draw(dial, dial_obj, 1, &r);
  482. #else
  483.         objc_draw(dial, dial_obj, 1, r.g_x, r.g_y, r.g_w, r.g_h);
  484. #endif
  485.     }
  486.     
  487.     return item;
  488. }
  489.